package com.zhouyu;

import com.zhouyu.service.*;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.jetbrains.annotations.NotNull;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.SimpleTypeConverter;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotatedBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.core.OrderComparator;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;

import javax.annotation.Nullable;
import javax.annotation.PostConstruct;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;

// 我的微信：dadudu6789
// 我的公众号：IT周瑜
public class Test {

	public static void main(String[] args) throws Exception {
		testSpring();
	}

	private static void testSpring() {
		// 创建一个Spring容器
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		UserService userService = context.getBean("userService", UserService.class);
		userService.test();
		userService.testTransactional1();
	}

	private static void testSpring2() {
		// 创建一个Spring容器
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

		UserService userService = (UserService) context.getBean("userService");
		userService.test();

		Object o1 = context.getBean("myFactoryBean");
		Object o2 = context.getBean("&myFactoryBean");

		context.publishEvent("hello spring");

		context.close();
	}

	private static void testBeanDefinition() {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
		beanDefinition.setBeanClass(User.class);
		beanDefinition.setScope("prototype");
		beanDefinition.setInitMethodName("init");
		beanDefinition.setLazyInit(true);
		context.registerBeanDefinition("user", beanDefinition);
		System.out.println(context.getBean("user"));
		System.out.println(context.getBean("user"));
	}

	private static void testAnnotatedBeanDefinitionReader() {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new AnnotatedBeanDefinitionReader(context);
		annotatedBeanDefinitionReader.register(User.class);
		System.out.println(context.getBean("user"));
	}

	private static void testXmlBeanDefinitionReader() {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(context);
		int i = xmlBeanDefinitionReader.loadBeanDefinitions("spring.xml");
		System.out.println(i);
		System.out.println(context.getBean("user1"));
	}

	private static void testClassPathBeanDefinitionScanner() {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
		context.refresh();
		ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
		scanner.scan("com.zhouyu");
		System.out.println(context.getBean("userService"));
	}

	private static void testDefaultListableBeanFactory() {
		DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
		AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
		beanDefinition.setBeanClass(User.class);
		beanFactory.registerBeanDefinition("user", beanDefinition);
		System.out.println(beanFactory.getBean("user"));
	}

	private static void testMessage() {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		System.out.println(context.getMessage("test", null, Locale.CHINESE));
		System.out.println(context.getMessage("test", null, Locale.ENGLISH));
	}

	private static void testResource() throws IOException {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		Resource resource = context.getResource("file:/Users/liuyinuo/Desktop/susong/Developer/spring-framework-5.3.10/tuling/src/main/java/com/zhouyu/AppConfig.java");
		System.out.println(resource.contentLength());
		System.out.println(resource.getFilename());
		resource = context.getResource("https://www.baidu.com");
		System.out.println(resource.contentLength());
		System.out.println(resource.getURL());
		resource = context.getResource("classpath:spring.xml");
		System.out.println(resource.contentLength());
		System.out.println(resource.getURL());
		Resource[] resources = context.getResources("classpath:com/zhouyu/*.class");
		for (Resource r : resources) {
			System.out.println(r.contentLength());
			System.out.println(r.getFilename());
		}
	}

	private static void testEnvironment() {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

		Map<String, Object> systemEnvironment = context.getEnvironment().getSystemEnvironment();
		System.out.println(systemEnvironment);

		System.out.println("=======");

		Map<String, Object> systemProperties = context.getEnvironment().getSystemProperties();
		System.out.println(systemProperties);

		System.out.println("=======");

		MutablePropertySources propertySources = context.getEnvironment().getPropertySources();
		System.out.println(propertySources);

		System.out.println("=======");

		System.out.println(context.getEnvironment().getProperty("NO_PROXY"));
		System.out.println(context.getEnvironment().getProperty("sun.jnu.encoding"));
		System.out.println(context.getEnvironment().getProperty("zhouyu"));
	}

	private static void testPublishEvent() {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		context.publishEvent("kkk");
	}

	private static void testPropertyEditor() {
		StringToUserPropertyEditor propertyEditor = new StringToUserPropertyEditor();
		propertyEditor.setAsText("1");
		User value = (User) propertyEditor.getValue();
		System.out.println(value);
	}

	private static void testPropertyEditor2() {
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
		UserService userService = (UserService) applicationContext.getBean("userService");
		userService.testUser();
	}

	private static void testConversionService() {
		DefaultConversionService conversionService = new DefaultConversionService();
		conversionService.addConverter(new StringToUserConverter());
		User user = conversionService.convert("jack", User.class);
		System.out.println(user);
	}

	private static void testConversionService2() {
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
		UserService userService = (UserService) applicationContext.getBean("userService");
		userService.testUser();
	}

	private static void testSimpleTypeConverter() {
		SimpleTypeConverter typeConverter = new SimpleTypeConverter();

		typeConverter.registerCustomEditor(User.class, new StringToUserPropertyEditor());

		DefaultConversionService conversionService = new DefaultConversionService();
		conversionService.addConverter(new StringToUserConverter());
		typeConverter.setConversionService(conversionService);

		User value = typeConverter.convertIfNecessary("1", User.class);
		System.out.println(value);
	}

	private static void testOrderComparator() {
		A a = new A(); // order=3
		B b = new B(); // order=2

		OrderComparator comparator = new OrderComparator();
		System.out.println(comparator.compare(a, b));  // 1

		List list = new ArrayList<>();
		list.add(a);
		list.add(b);

		// 按order值升序排序
		list.sort(comparator);

		System.out.println(list);  // B，A
	}

	private static void testOrderComparator2() {
		AA a = new AA(); // order=3
		BB b = new BB(); // order=2

		AnnotationAwareOrderComparator comparator = new AnnotationAwareOrderComparator();
		System.out.println(comparator.compare(a, b));  // 1

		List list = new ArrayList<>();
		list.add(a);
		list.add(b);

		// 按order值升序排序
		list.sort(comparator);

		System.out.println(list);  // B，A
	}

	private static void testFactoryBean() {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		UserService userService = (UserService) context.getBean("myFactoryBean");
		userService.test();
	}

	private static void testSimpleMetadataReader() throws IOException {
		SimpleMetadataReaderFactory simpleMetadataReaderFactory = new SimpleMetadataReaderFactory();
		MetadataReader metadataReader = simpleMetadataReaderFactory.getMetadataReader("com.zhouyu.service.UserService");
		ClassMetadata classMetadata = metadataReader.getClassMetadata();
		System.out.println(classMetadata.getClassName());

		AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
		for (String annotationType : annotationMetadata.getAnnotationTypes()) {
			System.out.println(annotationType);
		}
	}

	private static void testUserService() throws InvocationTargetException, IllegalAccessException {
		UserService userService1 = new UserService();

		for (Field field : userService1.getClass().getDeclaredFields()) {
			if (field.isAnnotationPresent(Autowired.class)) {
				field.set(userService1, null);
			}
		}

		for (Method method : userService1.getClass().getDeclaredMethods()) {
			if (method.isAnnotationPresent(PostConstruct.class)) {
				method.invoke(userService1);
			}
		}

		if (userService1 instanceof InitializingBean) {
			try {
				((InitializingBean) userService1).afterPropertiesSet();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	private static void testProxyFactory() {
		UserService userService1 = new UserService();
		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.setTarget(userService1);
		proxyFactory.addAdvice(new MethodInterceptor() {
			@Nullable
			@Override
			public Object invoke(@NotNull MethodInvocation invocation) throws Throwable {
				System.out.println("切面逻辑 before...");
				Object result = invocation.proceed();
//				Object result = invocation.getMethod().invoke(invocation.getThis(), invocation.getArguments());
				System.out.println("切面逻辑 after...");
				return result;
			}
		});
		UserService userService2 = (UserService) proxyFactory.getProxy();
		userService2.test();
	}

	private static void testGenericInject(){
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		SubService service = (SubService) context.getBean("subService");
		service.test();
	}
}







